//
//  GTWMSTileLayer.m
//  MyMap
//
//  Created by 朱国良 on 16/6/29.
//  Copyright © 2016年 朱国良. All rights reserved.
//
#ifdef DEBUG
#define PPLog(...) printf("[%s] %s [第%d行]: %s\n", __TIME__ ,__PRETTY_FUNCTION__ ,__LINE__, [[NSString stringWithFormat:__VA_ARGS__] UTF8String])
#else
#define PPLog(...)
#endif

#define TILE_SIZE 256

#import "UCWMSTileLayer.h"
#import <CommonCrypto/CommonDigest.h>
#import "UCWMSParameter.h"
#import <YYCache/YYCache.h>
#import "UCMapView+GSExtension.h"
#import "AeroMapServices.h"
#import "Public.h"
#import "AMNetworkTool.h"

@interface UCWMSTileLayer()
@property(nonatomic,strong)YYCache *cache;
@property(nonatomic,strong)NSString *cacheName;
@property(nonatomic,strong)AeroMapServices *service;
//@property(nonatomic,strong)NSURLSession *section;
@end

@implementation UCWMSTileLayer

- (void)dealloc{
    
    //    NSLog(@"😭😭😭😭图层被释放掉了😭😭😭😭");
}


- (instancetype)initWithLayerParameter:(UCWMSParameter *)parameter{
    
    self = [super init];
    if (self) {
        self.parameter = parameter;
        self.layerName = self.parameter.layerKey;
        
        self.cache = [YYCache cacheWithName:@"AirMapSDK"];
        
        self.service = [AeroMapServices shareServices];
        
//        self.section = [NSURLSession sharedSession];
    }
    return self;
}

- (CGFloat)xOfColumn:(NSInteger)column withZoom:(NSInteger)zoom{
    
    CGFloat originShift = 2 * M_PI * 6378137 / 2.0;
    CGFloat res = 2 * M_PI * 6378137/TILE_SIZE / pow(2.0, zoom);
    
    CGFloat maxX = column * TILE_SIZE * res - originShift;
    maxX = maxX / originShift * 180.0;
    return maxX;
}

- (CGFloat)yOfRow:(NSInteger)row withZoom:(NSInteger)zoom{
    
    CGFloat originShift = 2 * M_PI * 6378137 / 2.0;
    CGFloat res = 2 * M_PI * 6378137/TILE_SIZE / pow(2.0, zoom);
    
    CGFloat minY = originShift - row * TILE_SIZE * res;
    minY = minY / originShift * 180.0;
    minY = 180 / M_PI * (2 * atan(exp(minY * M_PI / 180.0)) - M_PI / 2.0);
    return minY;
}

- (bbox)bboxFromX:(NSInteger)x Y:(NSInteger)y Z:(NSInteger)z{
    
    double left = [self xOfColumn:x withZoom:z];
    double right = [self xOfColumn:x+1 withZoom:z];
    double bottom = [self yOfRow:y+1 withZoom:z];
    double top = [self yOfRow:y withZoom:z];
    
//    CLLocationCoordinate2D leftTop = [self.parameter.mapView gcj02ToWgs84WithLocation:CLLocationCoordinate2DMake(top, left)];
//    CLLocationCoordinate2D buttomRight = [self.parameter.mapView gcj02ToWgs84WithLocation:CLLocationCoordinate2DMake(bottom, right)];
    
//    left = leftTop.longitude;
//    top = leftTop.latitude;
//    bottom = buttomRight.latitude;
//    right = buttomRight.longitude;
    
    bbox b = {
        .left   = left,     //minX
        .right  = right,    //maxX
        .bottom = bottom,   //maxY
        .top    = top       //minY
    };
    return b;
}


- (NSString*)getUrlX: (NSUInteger) x Y:(NSUInteger)y Z:(NSUInteger)z{
    //    https://mt0.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x=863509&y=397120&z=20&scale=2
//        NSString *url = [NSString stringWithFormat:@"https://mt0.google.cn/vt/lyrs=m&hl=zh-CN&gl=cn&x=%lu&y=%lu&z=%lu&scale=2",(unsigned long)x,(unsigned long)y,(unsigned long)z];
    
    NSString *url = [NSString stringWithFormat:@"%@/%@/%lu/%lu/%lu?%@%@",UCMAPTITLEURL,self.parameter.mapType,(unsigned long)z, (unsigned long)y, (unsigned long)x,UCMAPKEY,[self.service valueForKey:@"AeroMapAK"]];
    
    if (self.titleLayerType == WMSTitleLayerOverlay) {
        bbox b = [self bboxFromX:x Y:y Z:z];
        if (self.parameter.filter) {
            url = [NSString stringWithFormat:@"%@?SERVICE=WMS&REQUEST=GetMap&VERSION=1.1.1&LAYERS=%@&STYLES=&FORMAT=image%%2Fpng&TRANSPARENT=true&HEIGHT=256&WIDTH=256&ZINDEX=%lu&BUFFER=40&CQL_FILTER=%@&SRS=EPSG%%3A4326&BBOX=%f,%f,%f,%f&%@%@",self.parameter.url,self.parameter.name,(unsigned long)z,self.parameter.filter,b.left, b.bottom,b.right,b.top,UCMAPKEY,[self.service valueForKey:@"AeroMapAK"]];
        }else{
            url = [NSString stringWithFormat:@"%@?SERVICE=WMS&REQUEST=GetMap&VERSION=1.1.1&LAYERS=%@&STYLES=&FORMAT=image%%2Fpng&TRANSPARENT=true&HEIGHT=256&WIDTH=256&ZINDEX=%lu&BUFFER=%ld&SRS=EPSG%%3A4326&BBOX=%f,%f,%f,%f&%@%@",self.parameter.url,self.parameter.name,(unsigned long)z,(long)self.parameter.buffer,b.left, b.bottom,b.right,b.top,UCMAPKEY,[self.service valueForKey:@"AeroMapAK"]];
        }
    }
    return url;
}

- (void)requestTileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)z receiver:(id<GMSTileReceiver>)receiver{
    NSString *URL = [self getUrlX:x Y:y Z:z];
    if (!URL){
        [receiver receiveTileWithX:x y:y zoom:z image:kGMSTileLayerNoTile];
        return;
    }
    
    // 1.网络请求者
    AMNetworkTool *manager = [AMNetworkTool shareIntance];
//     2.读取缓存中的etag
    NSString *value = [self getEtagKey:URL];
    if (value) {
        [manager.requestSerializer setValue:value forHTTPHeaderField:@"If-None-Match"];
    }else{
        //读取地图缓存（没有Etag）
        [self.cache objectForKey:URL withBlock:^(NSString * _Nonnull key, id<NSCoding>  _Nonnull object) {
            UIImage *image = (UIImage *)object;
            if (image) {
                [receiver receiveTileWithX:x y:y zoom:z image:image];
                return ;
            }
        }];
    }
    
    __weak typeof(self) weakSelf = self;
    // 3.获取瓦片
    [self loadMapTitleWithUrl:URL finished:^(NSInteger statusCode,UIImage *image,NSDictionary *dic, NSError *error) {
        
        if (statusCode == 200){
            [weakSelf successCompletionHandle:image
                              requestTileForX:x
                                            y:y
                                            zoom:z
                                     receiver:receiver];
            //将etag保存起来 图层有Etag
            if (weakSelf.openCache) {
                if (dic[@"Etag"]) {
                    [weakSelf.cache setObject:dic[@"Etag"] forKey:[URL stringByAppendingString:@"Etag"] withBlock:^{
                    }];
                }
                [weakSelf.cache setObject:image forKey:URL withBlock:^{
                }];
            }
            return ;
        }else if (statusCode == 304){
            //读取缓存
            UIImage *image = (UIImage *)[weakSelf.cache objectForKey:URL];
            if (image) {
                [receiver receiveTileWithX:x
                                         y:y
                                      zoom:z
                                     image:[weakSelf getImageWithData:image]];
            }else{
                [receiver receiveTileWithX:x
                                         y:y
                                      zoom:z
                                     image:kGMSTileLayerNoTile];
            }
            return ;
        }else if (statusCode == 401){
            NSLog(@"AeroMap Error:AK验证失败");
            [receiver receiveTileWithX:x
                                     y:y
                                  zoom:z
                                 image:kGMSTileLayerNoTile];
        }else{
            [weakSelf.cache objectForKey:URL withBlock:^(NSString * _Nonnull key, id<NSCoding>  _Nonnull object) {
                UIImage *image = (UIImage *)object;
                if (image) {
                    [receiver receiveTileWithX:x
                                             y:y
                                          zoom:z
                                         image:[weakSelf getImageWithData:image]];
                }else{
                    [receiver receiveTileWithX:x
                                             y:y
                                          zoom:z
                                         image:kGMSTileLayerNoTile];
                }
            }];
        }
    }];
}



- (void)loadMapTitleWithUrl:(NSString *)url finished:(void(^)(NSInteger statusCode,UIImage *image,NSDictionary *dic,NSError *error))block{
    
    [[AMNetworkTool shareIntance] GET:url parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        // 1.获取相应的状态码
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
        NSInteger statusCode = httpResponse.statusCode;
        UIImage *image = [UIImage imageWithData:responseObject];
        block ? block(statusCode,image,httpResponse.allHeaderFields,nil) : nil;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
        NSInteger statusCode = httpResponse.statusCode;
        block ? block(statusCode,nil,nil,error) : nil;
    }];
}

- (NSString *)getEtagKey:(NSString *)url{
    NSString *key = [url stringByAppendingString:@"Etag"];
    NSString *etag = (NSString *)[self.cache objectForKey:key];
    return etag;
}

- (void)successCompletionHandle:(id)responseObject requestTileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)z receiver:(id<GMSTileReceiver>)receiver
{
    UIImage *image = responseObject;
    if (self.titleLayerType == WMSTitleLayerOverlay) {
        image = [self getImageWithData:image];
    }
    if (image) {
        [receiver receiveTileWithX:x y:y zoom:z image:image];
    }else{
        [receiver receiveTileWithX:x y:y zoom:z image:kGMSTileLayerNoTile];
    }
}

- (UIImage *)getImageWithData:(UIImage *)image{
    
    //设置图形上下文
    if ([image isKindOfClass:[UIImage class]]) {
        UIGraphicsBeginImageContext(image.size);
        //设置绘制的图片区域
        CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
        [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1];
        //获取当前的图形上下文
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 0.0);
        CGContextSetLineWidth(context, 1.0);
        CGContextStrokeRect(context, rect);
        image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    return kGMSTileLayerNoTile;
}

@end
